package main.userInterface.islandui;


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import javax.swing.JPanel;

import main.model.island.IslandInterface;
import main.model.island.RandomIsland;
import main.model.island.grid.GridTree;
import main.model.island.grid.GridType;
import main.model.island.listener.IslandListener;


@Deprecated
@SuppressWarnings("serial")
public class IslandCanvas extends JPanel {

	/*Colour palate*/
	private static final Color WATER = Color.blue;
	private static final Color SAND = new Color(224,194,64);
	private static final Color GRASS = new Color(102,255,109);
	private static final Color TREEG = new Color(0,151,8);
	private static final Color TREEB = new Color(210,104,0);

	private IslandInterface island;

	//Grid Dimensions//
	private int ZOOM = 15;
	private double CORNER, SEA, BEACH, SEBE, TREE, TOKEN, ISLX ,ISLY; 
	private int Xmax = 0, Ymax = 0; //Size of island
	private ArrayList<IslTile> tileArray = null;
	
	//Display booleans//
	private boolean gridref = true; //Grid numbers, on or off
	private boolean gridline = true; //Grid lines, on or off
	private boolean displaycritters = false;
	private boolean rounding = true;


	public IslandCanvas(IslandInterface island) {
		setIsland(island);
		setZoom(ZOOM);
		setBackground(WATER);
		
	}

	public void paintComponent(Graphics g){
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D)g;
		
		if(rounding){
			RenderingHints hints = new RenderingHints(
					RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			hints.add(new RenderingHints(
					RenderingHints.KEY_RENDERING, 
					RenderingHints.VALUE_RENDER_QUALITY));
			g2.setRenderingHints(hints);
		}else{
			RenderingHints hints = new RenderingHints(
					RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_OFF);
			hints.add(new RenderingHints(
					RenderingHints.KEY_RENDERING, 
					RenderingHints.VALUE_RENDER_SPEED));
			g2.setRenderingHints(hints);
		}
		
		drawIslandTiles(g2);
		drawIslandRefs(g2);
		drawIslandTrees(g2);
		//drawCritters(g2);
	}

	/**
	 * Draws grid lines and grid references for the island.
	 * @param g
	 */
	private void drawIslandRefs(Graphics2D g) {
		//SETTING grid numbers
		Graphics2D g2 = (Graphics2D)g;
		if(gridref){
			g2.setPaint(Color.white);
			g2.setFont(new Font("Papyrus",Font.PLAIN, 10));
			FontMetrics metrics = g2.getFontMetrics();
			//Create and place text along X
			for(int x=0;x<Xmax;x=x+3){
                String text = ""+(char)(65+(x/3));
				int hx = (int)(SEBE+x*ZOOM+(ZOOM*3)/2 - metrics.stringWidth(text)/2);
				int hy = (int)(SEA/2 + (metrics.getHeight()/4));
				g2.drawString(text, hx, hy);
			}
			//Create and place text down Y
			for(int y=0;y<Ymax;y=y+3){
                String text = ""+y/3;
				int hx = (int)(SEA/2 - metrics.stringWidth(text)/2);
				int hy = (int)(SEBE+y*ZOOM+(ZOOM*3)/2 + (metrics.getHeight()/4) );
				g2.drawString(text, hx, hy);
			}
		}
		
		//SETTING grid lines
		if(gridref){
			g2.setStroke(new BasicStroke(1));
			g2.setPaint(Color.red);
			for(int x=3; x < Xmax ;x = x+3){
				double x1 = SEBE + x*ZOOM;  double y1 = SEA/2;
				double x2 = SEBE + x*ZOOM;  double y2 = SEBE+ISLY+BEACH+SEA/2;
				g2.draw(new Line2D.Double(x1,y1,x2,y2));
			}
			for(int y=3 ; y < Ymax; y= y+3){
				double x1 = SEA/2 ;  double y1 = SEBE+y*ZOOM;
				double x2 = SEBE+ISLX+BEACH+SEA/2;  double y2 = SEBE+y*ZOOM;
				g2.draw(new Line2D.Double(x1,y1,x2,y2));
			}
		}
	}

	/**
	 * Draws the trees for the island.
	 * @param g
	 */
	private void drawIslandTrees(Graphics2D g) {
		Graphics2D g2 = (Graphics2D)g;
		for(int x = 0 ; x < island.getXSize(); x++){	
			for(int y = 0; y < island.getYSize(); y++){
				if(island.getGridType(x, y) == GridType.TREE){
					double rx = SEBE+x*ZOOM+ZOOM/2-TREE/2;
					double ry = SEBE+y*ZOOM+ZOOM/2-TREE/2;
					g2.setPaint(TREEB); g2.fill(new Ellipse2D.Double(rx,ry,TREE,TREE));
					
					GridTree t = (GridTree) island.getGrid(x, y);

					double angle = 3.6*(100/t.getTreeMax()*t.getTree());
					g2.setPaint(TREEG); g2.fill(new Arc2D.Double(rx,ry,TREE,TREE,angle,360-angle,Arc2D.PIE));
					
				}
			}
		}
	}

	/**
	 * Draws the tiles for the island.
	 * Obeys the rounded parameter.
	 * @param g
	 */
	private void drawIslandTiles(Graphics2D g) {
		Graphics2D g2 = (Graphics2D)g;
		g2.setPaint(SAND);
		g2.fill(new RoundRectangle2D.Double(SEA, SEA, ISLX+BEACH*2, ISLY+BEACH*2, ZOOM, ZOOM));
		
		if(rounding){
			if(tileArray == null){
				tileGenerator();
			}
			for(int i = 0; i < tileArray.size(); i++){
				g2.setPaint(tileArray.get(i).getColor());
				g2.fill(tileArray.get(i).getTile());
			}
			
			for(int x = 0 ; x < island.getXSize(); x++){	
				for(int y = 0; y < island.getYSize(); y++){

					if(island.getGridType(x, y) == GridType.SAND){
						g2.setPaint(SAND);
					}else if(island.getGridType(x, y) == GridType.GRASS || island.getGridType(x, y) == GridType.TREE){
						g2.setPaint(GRASS);
					}else{
						g2.setPaint(Color.BLACK);
					}
					g2.fill(new RoundRectangle2D.Double(SEBE+x*ZOOM,SEBE+y*ZOOM, ZOOM, ZOOM, CORNER, CORNER));
				}
			}
		}

		else{
			for(int x = 0 ; x < island.getXSize(); x++){	
				for(int y = 0; y < island.getYSize(); y++){

					if(island.getGridType(x, y) == GridType.SAND){
						g2.setPaint(SAND);
					}else if(island.getGridType(x, y) == GridType.GRASS || island.getGridType(x, y) == GridType.TREE){
						g2.setPaint(GRASS);
					}else{
						g2.setPaint(Color.BLACK);
					}
					g2.fill(new Rectangle2D.Double(SEBE+x*ZOOM, SEBE+y*ZOOM, ZOOM, ZOOM));
				}
			}
		}
	}

	/**
	 * Reduces calculations by storing rounding tiles.
	 * Makes all rounding calculations and stores them in an arraylist.
	 */
	private void tileGenerator(){
		tileArray = new ArrayList<IslTile>();

		//NORTH and SOUTH edge Smoothing
		for(int x = 0 ; x < island.getXSize()-1; x++){
			String a = island.getGridType(x, 0).getBase();
			String b = island.getGridType(x+1, 0).getBase();

			if(a.equals(b)){
				if(a.equals(GridType.GRASS.getBase())){
					tileArray.add(new IslTile(GRASS, new Rectangle2D.Double(
							SEBE+(x*ZOOM)+ZOOM/2, SEBE, ZOOM, ZOOM/2)));
				}
			}
			a = island.getGridType(x, Ymax-1).getBase();
			b = island.getGridType(x+1, Ymax-1).getBase();
			if(a.equals(b)){
				if(a.equals(GridType.GRASS.getBase())){
					tileArray.add(new IslTile(GRASS, new Rectangle2D.Double(
							SEBE+(x*ZOOM)+ZOOM/2, SEBE+ISLY-ZOOM/2, ZOOM, ZOOM/2)));
				}
			}
		}
		
		//EAST and WEST edge smoothing	
		for(int y = 0; y < island.getYSize()-1; y++){
			String a = island.getGridType(0, y).getBase();
			String b = island.getGridType(0, y+1).getBase();

			if(a.equals(b)){
				if(a.equals(GridType.GRASS.getBase())){
					tileArray.add(new IslTile(GRASS,new Rectangle2D.Double(
							SEBE, SEBE+(y*ZOOM)+ZOOM/2, ZOOM/2, ZOOM)));
				}
			}

			a = island.getGridType(Xmax-1, y).getBase();
			b = island.getGridType(Xmax-1, y+1).getBase();

			if(a.equals(b)){
				if(a.equals(GridType.GRASS.getBase())){
					tileArray.add(new IslTile(GRASS,new Rectangle2D.Double(
							SEBE+ISLX-ZOOM/2, SEBE+(y*ZOOM)+ZOOM/2, ZOOM/2, ZOOM)));
				}
			}
		}

		//INTERNAL edge smoothing	
		for(int x = 0 ; x < island.getXSize()-1; x++){	
			for(int y = 0; y < island.getYSize()-1; y++){

				String a,b,c,d;
				a = island.getGridType(x,y).getBase();
				b = island.getGridType(x+1,y).getBase();
				c = island.getGridType(x,y+1).getBase();
				d = island.getGridType(x+1,y+1).getBase();
				//A B
				//C D
				double cx = SEBE+(x*ZOOM)+(ZOOM/2);    double cy = SEBE+(y*ZOOM)+(ZOOM/2);

				if((a.equals(d) && a.equals(GridType.GRASS.getBase())) 
						|| (b.equals(c) && b.equals(GridType.GRASS.getBase()))){

					tileArray.add(new IslTile(GRASS, new Rectangle2D.Double(cx,cy,ZOOM,ZOOM)));

				}else{
					int GrassCount = 0;
					if(a.equals(GridType.GRASS.getBase())){GrassCount++;}
					if(b.equals(GridType.GRASS.getBase())){GrassCount++;}
					if(c.equals(GridType.GRASS.getBase())){GrassCount++;}
					if(d.equals(GridType.GRASS.getBase())){GrassCount++;}

					//3-4 grasses is grass
					if(GrassCount >= 3){
						tileArray.add(new IslTile(GRASS, new Rectangle2D.Double(cx,cy,ZOOM,ZOOM)));
					}
					//1 or less is sand
					else if(GrassCount<=1){
					}

					//A = B is horizontal
					else if(a.equals(b)){
						//top
						if(a.equals(GridType.GRASS.getBase())){
							tileArray.add(new IslTile(GRASS, new Rectangle2D.Double(cx,cy,ZOOM,ZOOM/2)));
						}
						//bottom
						else{
							tileArray.add(new IslTile(GRASS, new Rectangle2D.Double(cx,cy+(ZOOM/2),ZOOM,ZOOM/2)));
						}
					}
					//A = C is vertical
					else if(a.equals(c)){
						//left
						if(a.equals(GridType.GRASS.getBase())){
							tileArray.add(new IslTile(GRASS, new Rectangle2D.Double(cx,cy,ZOOM/2,ZOOM)));
						}
						//right
						else{
							tileArray.add(new IslTile(GRASS, new Rectangle2D.Double(cx+(ZOOM/2),cy,ZOOM/2,ZOOM)));
						}
					}
				}
			}
		}
	}

	
	/**
	 * Sets the Zoom and all other parameters based from that figure
	 * @param ZOOM
	 */
	public void setZoom(double ZOOM){
		Xmax = island.getXSize();
		Ymax = island.getYSize();
		this.ZOOM = (int) ZOOM;
		CORNER = ZOOM/2;
		SEA = 20; //Sea
		BEACH = ZOOM/2; //Beach
		SEBE = (int)SEA+(int)BEACH; //sea and sand size
		TREE = ZOOM+(ZOOM/5);//tree size
		TOKEN = ZOOM/2-(ZOOM/5); //triangle size
		ISLX = ZOOM * Xmax; //The Width of the island
		ISLY = ZOOM * Ymax; //pixels

		tileArray = null;
		
		this.setPreferredSize(new Dimension((int)((SEBE*2)+ISLX), (int)((SEBE*2)+ISLY)));
		repaint();
	}
	
	
	
	public void setIsland(IslandInterface island){
		this.island = island;
		island.addIslandListener(new IslandListener(){
			public void changeEvent() {
				//tileArray = null;
				setZoom(ZOOM);
			}
		});
		setZoom(ZOOM);
	}
	
	public void setGridLine(boolean setGL){gridline=setGL; repaint();}
	public boolean getGridLine(){return gridline;}
	public void setGridRef(boolean setGR){gridref=setGR; repaint();}
	public boolean getGridRef(){return gridref;}
	public void setRounded(boolean rounded){rounding = rounded; repaint();}
	public boolean getRounded(){return rounding;}
	
	public int getXbyMouse(int xmouse){
		if(xmouse>SEBE && xmouse<SEBE+ISLX){
			return (int)((xmouse-SEBE)/ZOOM);
		} else {
			return -1;
		}
	}
	
	public int getYbyMouse(int ymouse){
		if(ymouse>SEBE && ymouse<SEBE+ISLY){
			return (int)((ymouse-SEBE)/ZOOM);
		} else {
			return -1;
		}
	}
	
	public IslandInterface getIsland() {
		return island;
	}
	
	public class IslTile{
		private Rectangle2D.Double tile;
		private Color color;

		public IslTile(Color color, Rectangle2D.Double tile){
			this.tile = tile;
			this.color = color;
		}
		public Rectangle2D.Double getTile(){
			return tile;
		}
		public Color getColor(){
			return color;
		}
	}
}
